@@ -1 +1,72 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 1 | 2 |
|
| 3 |
+from django.db import IntegrityError, transaction |
|
| 4 |
+from django.utils import timezone |
|
| 5 |
+from django_logit import logit |
|
| 6 |
+from django_response import response |
|
| 7 |
+from django.db.models import Q |
|
| 8 |
+ |
|
| 9 |
+from account.models import UserInfo |
|
| 10 |
+from sales.models import LotteryCampaignInfo, LotteryEntryInfo |
|
| 11 |
+from utils.error.errno_utils import LotteryStatusCode, UserStatusCode |
|
| 12 |
+ |
|
| 13 |
+def join_lottery(user, serial_no, model_id='', campaign_id='', submit_pk='', phone='', model_name=''): |
|
| 14 |
+ """ |
|
| 15 |
+ 写入抽奖名额(幂等) |
|
| 16 |
+ |
|
| 17 |
+ 返回 (entry, campaign, is_new): |
|
| 18 |
+ · 没有进行中的活动 → (None, None, False) |
|
| 19 |
+ · 已有名额 → (entry, campaign, False) |
|
| 20 |
+ · 首次参与 → (entry, campaign, True) |
|
| 21 |
+ """ |
|
| 22 |
+ serial_no = (serial_no or '').strip() |
|
| 23 |
+ |
|
| 24 |
+ campaign = LotteryCampaignInfo.objects.get(status=True, campaign_id=campaign_id) |
|
| 25 |
+ |
|
| 26 |
+ if not campaign: |
|
| 27 |
+ return None, None |
|
| 28 |
+ |
|
| 29 |
+ # 嵌套 atomic 生成 savepoint:并发插入冲突后还能继续查询 |
|
| 30 |
+ with transaction.atomic(): |
|
| 31 |
+ entry, created = LotteryEntryInfo.objects.get_or_create( |
|
| 32 |
+ campaign_id=campaign.campaign_id, |
|
| 33 |
+ serial_no=serial_no, |
|
| 34 |
+ submit_pk=submit_pk, |
|
| 35 |
+ title=campaign.title, |
|
| 36 |
+ phone=phone, |
|
| 37 |
+ user_id=user.user_id, |
|
| 38 |
+ model_id=model_id, |
|
| 39 |
+ model_name=model_name, |
|
| 40 |
+ ) |
|
| 41 |
+ |
|
| 42 |
+ return entry, campaign |
|
| 43 |
+ |
|
| 44 |
+ |
|
| 45 |
+@logit(res=True) |
|
| 46 |
+@transaction.atomic |
|
| 47 |
+def lottery_join_api(request): |
|
| 48 |
+ """抽奖参与接口:写入名额""" |
|
| 49 |
+ user_id = request.POST.get('user_id', '')
|
|
| 50 |
+ serial_no = request.POST.get('serial_no')
|
|
| 51 |
+ model_id = request.POST.get('model_id')
|
|
| 52 |
+ campaign_id = request.POST.get('campaign_id', '')
|
|
| 53 |
+ submit_pk = request.POST.get('submit_pk', '')
|
|
| 54 |
+ phone = request.POST.get('phone', '')
|
|
| 55 |
+ model_name = request.POST.get('model_name', '')
|
|
| 56 |
+ |
|
| 57 |
+ try: |
|
| 58 |
+ user = UserInfo.objects.select_for_update().get(user_id=user_id) |
|
| 59 |
+ except UserInfo.DoesNotExist: |
|
| 60 |
+ return response(UserStatusCode.USER_NOT_FOUND) |
|
| 61 |
+ |
|
| 62 |
+ # TODO 安全:应校验该序列号确实绑定在当前用户名下,防止传入他人序列号刷名额 |
|
| 63 |
+ |
|
| 64 |
+ entry, campaign = join_lottery(user, serial_no, model_id, campaign_id, submit_pk, phone, model_name) |
|
| 65 |
+ |
|
| 66 |
+ if not campaign: |
|
| 67 |
+ return response(LotteryStatusCode.CAMPAIGN_NOT_FOUND) |
|
| 68 |
+ |
|
| 69 |
+ return response(200, data={
|
|
| 70 |
+ 'campaign': serialize_campaign(campaign), |
|
| 71 |
+ 'entry': serialize_entry(entry), |
|
| 72 |
+ }) |
@@ -5,4 +5,5 @@ from django.conf.urls import include, url |
||
| 5 | 5 |
from api.sale import lottery_views |
| 6 | 6 |
|
| 7 | 7 |
urlpatterns = [ |
| 8 |
+ url(r'^sale/lottery/join$', lottery_views.lottery_join_api, name='lottery_join_api'), |
|
| 8 | 9 |
] |
@@ -234,3 +234,8 @@ class ContractStatusCode(BaseStatusCode): |
||
| 234 | 234 |
class TencentCloudStatusCode(BaseStatusCode): |
| 235 | 235 |
""" 腾讯云SDK错误码 5099xx """ |
| 236 | 236 |
TENCENT_CLOUD_SDK_EXCEPTION = StatusCodeField(509901, 'Tencent Cloud SDK Exception', description=u'腾讯云SDK报错') |
| 237 |
+ |
|
| 238 |
+ |
|
| 239 |
+class LotteryStatusCode(BaseStatusCode): |
|
| 240 |
+ """ 抽奖相关错误码 5099xx """ |
|
| 241 |
+ CAMPAIGN_NOT_FOUND = StatusCodeField(509902, 'Campaign Not Found', description=u'抽奖活动不存在') |